package org.sgs.reddit.bot.log;

import java.util.logging.Level;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class LogUtils {
	
	private static StackTraceElement getCallingElement(){
		StackTraceElement[] elements = new Exception().fillInStackTrace().getStackTrace();
		for(StackTraceElement element : elements){
			String className = element.getClassName();
			if(!className.equals(LogUtils.class.getName())){
				return element;
			}
		}
		throw new RuntimeException("Could not determine calling class.");
	}
	
	
	private static void doLogging(Level level, StackTraceElement element, LogMessage logMessage){
		
		if(level == Level.OFF){
			return;
		}
		
		String message = getCustomMessage(element, logMessage);
		
		String className = element.getClassName();
		Log log = LogFactory.getLog(className);
		
		if(level == Level.SEVERE && log.isFatalEnabled()){
			// Fatal
			log.fatal(message);
		}else if(level == Level.WARNING && log.isErrorEnabled()){
			// Error
			log.error(message);
		} else if(level == Level.INFO && log.isWarnEnabled()){
			// Warn
			log.warn(message);
		} else if (level == Level.FINE && log.isInfoEnabled()){
			// Info
			log.info(message);
		} else if (level == Level.FINER && log.isDebugEnabled()){
			// Debug
			log.debug(message);
		} else if (level == Level.FINEST && log.isTraceEnabled() ){
			// Trace
			log.trace(message);
		}
	}
	
	private static String getCustomMessage(StackTraceElement element, LogMessage message){
		String className = element.getClassName();
		String methodName = element.getMethodName();
		int lineNum =  element.getLineNumber();
		return String.format("%s.%s(%d): %s", className, methodName, lineNum, message);
	}
	
	public static void trace(String format, Object...args){
		StackTraceElement element = getCallingElement();
		doLogging(Level.FINEST, element, new LogMessage(format, args));
	}
	
	public static void debug(String format, Object...args){
		StackTraceElement element = getCallingElement();
		doLogging(Level.FINER, element, new LogMessage(format, args));
	}

	public static void info(String format, Object...args){
		StackTraceElement element = getCallingElement();
		doLogging(Level.FINE, element, new LogMessage(format, args));
	}
	
	public static void warn(String format, Object...args){
		StackTraceElement element = getCallingElement();
		doLogging(Level.INFO, element, new LogMessage(format, args));
	}
	
	public static void error(String format, Object...args){
		StackTraceElement element = getCallingElement();
		doLogging(Level.WARNING, element, new LogMessage(format, args));
	}
	
	public static void fatal(String format, Object...args){
		StackTraceElement element = getCallingElement();
		doLogging(Level.SEVERE, element, new LogMessage(format, args));
	}
	
}
